#include "entityfactory.h"

void CEntityVec::AddEntity( CEntity * e )
{
	
	m_pEntities[e->GetUniqueID()] = e;
	
	m_pDrawOrder.push_back( e );
	
}

CEntity * CEntityStateVec::NewEntity()
{

	CEntity * e = new CEntity;
	
	AddEntity( e );
	
	return e;
	
}

void CEntityStateVec::BeginIterate()
{
	
	m_IterBegin = m_pMappedEntities.begin();
	
}

CEntity * CEntityStateVec::IterateNextEntity()
{
	
	CEntity * e = NULL;
	
	if( m_IterBegin == m_pMappedEntities.end() )
		return NULL;
	
	e = m_IterBegin->second;
	
	m_IterBegin++;
	
	return e;
	
}

CEntity * CEntityStateVec::AddEntity( CEntity * e )
{

	if( !m_pEntities[e->GetClass()] )
		m_pEntities[e->GetClass()] = new CEntityVec;
	
	e->SetEntityInterface( m_pEntityInterface );
	
	m_pMappedEntities[e->GetUniqueID()] = e;
	
	m_pEntities[e->GetClass()]->AddEntity( e );
	
	return e;
	
}

void CEntityStateVec::RemoveAllEntities()
{
	
		for( std::map< std::string, CEntityVec * >::iterator iter = m_pEntities.begin();
			 iter != m_pEntities.end(); iter++ )
			{
				
				
				( iter->second )->RemoveAllEntities();
				
			}
			
		m_pMappedEntities.clear();
	
}

void CEntityStateVec::RemoveEntity( int id )
	{
		
		try 
		{
			
			m_pMappedEntities.erase( id );
			
		} catch( std::exception & err ) { }
		
		
		for( std::map< std::string, CEntityVec * >::iterator iter = m_pEntities.begin();
			 iter != m_pEntities.end(); iter++ )
			{
				
				
				if( ( iter->second )->RemoveEntity( id ) )
					break;
				
			}
					
		
	}

CEntity * CEntityStateVec::GetEntity( int id )
{
	
	CEntity * e = NULL;
	
	try
	{
		
		e = m_pMappedEntities.at( id );
		
		if( e )
			return e;
		
	} catch( std::exception & err ) { }
	
	for( std::map< std::string, CEntityVec * >::iterator iter = m_pEntities.begin();
		iter != m_pEntities.end(); iter++ )
		{
			
			e = ( iter->second )->GetEntity( id );
			
			if( e )
			{
				
				m_pMappedEntities[id] = e;
				return e;
				
			}
			
		}
		
	return NULL;
		
}	


CEntityStateVec::~CEntityStateVec()
{
	
	for( std::map< std::string, CEntityVec * >::iterator iter = m_pEntities.begin();
		 iter != m_pEntities.end(); iter++ )
		{
		
			CEntityVec * v = iter->second;
			
			if( v )
			{
			
				delete v;
			
				v = NULL;
				
			}
			
		}
		
	m_pEntities.clear();
	
}

void CEntityVec::RemoveAllEntities()
{
	
	for( std::map< int, CEntity * >::iterator iter = m_pEntities.begin();
		 iter != m_pEntities.end(); iter++ )
		{
		
			CEntity * o = iter->second;
			delete o;
			o = NULL;
			
		}
		
	m_pEntities.clear();
	m_pDrawOrder.clear();
	
}

CEntityVec::~CEntityVec()
{
	
	RemoveAllEntities();
	
}

void CEntityVec::Think()
{
	
	for( std::map< int, CEntity * >::iterator iter = m_pEntities.begin();
		 iter != m_pEntities.end(); iter++ )
		{
		
			CEntity * o = iter->second;
			
			o->Think();
			
		}
	
}

void CEntityStateVec::EntitiesThink()
{
	
	for( std::map< std::string, CEntityVec * >::iterator iter = m_pEntities.begin();
		 iter != m_pEntities.end(); iter++ )
		{
		
			iter->second->Think();
			
		}
	
}

void CEntityVec::EntityCollidingWithEntities( CEntity * ent, CCollisionReport & cr )
{
	
	for( std::map< int, CEntity * >::iterator iter = m_pEntities.begin();
		 iter != m_pEntities.end(); iter++ )
		{
			
			CEntity * o = iter->second;
			
			if( ent != o )
			{
				
				CCollisionData cd;
			
				if( ent->IsCollidingWith( o, cd ) )
				{
					
					cd.recID = o->GetUniqueID();
					cr.m_CollisionData.push_back( cd );
				
				}
					
			}
			
		}
	
}

bool CEntityStateVec::EntityCollidingWithEntities( CEntity * ent, CCollisionReport & cr )
{
	
	for( std::map< std::string, CEntityVec * >::iterator iter = m_pEntities.begin();
		 iter != m_pEntities.end(); iter++ )
		{
		
			CEntityVec * v = iter->second;
			
			 v->EntityCollidingWithEntities( ent, cr );
			
		}
		
	return ( cr.count() > 0 );
	
}

bool SortDrawEnts( CEntity * e1, CEntity * e2 )
{
	
	float y1 = e1->GetPos().y + e1->GetSize().y;
	float y2 = e2->GetPos().y + e2->GetSize().y;
	
	return( y1 <= y2 );
	
}

void CEntityVec::SortDrawOrder()
{
	
	std::sort( m_pDrawOrder.begin(), m_pDrawOrder.end(), SortDrawEnts );
	
}



void CEntityVec::DrawEntities( CFrameScene * pFrameScene )
{
	
	SortDrawOrder();
	
	int curBuffer = -1;
	
	float transx = 0.0f, transy = 0.0f;
	
#ifdef DRAW_OPENGL_2
	
	float matrix[16];
	Draw::GetMatrix( matrix );
	
	transx = matrix[12];
	transy = matrix[13];

#elif defined( DRAW_OPENGL_3 )

	float * trans = Draw::GetTranslate();
	
	transx = trans[0];
	transy = trans[1];

#endif

	for( std::vector< CEntity * >::iterator iter = m_pDrawOrder.begin();
		 iter != m_pDrawOrder.end(); iter++ )
		{
		
			CEntity * o = ( *iter );
			
			if( curBuffer < 0 || curBuffer != o->GetDrawLayer() )
			{
				
				curBuffer = o->GetDrawLayer();
				
				if( pFrameScene )
				{
					
					pFrameScene->BindFrameBufferObject( curBuffer );
				
					CLEAR_BUFFER;
					
				}	
				
			
			}
			
			PUSH_MATRIX;
			
				Draw::Translate( transx, transy, 0.0f );
				o->Draw();
			
			POP_MATRIX;
				
		}
		
	if( pFrameScene )
		pFrameScene->UnbindFrameBufferObject();
	
}

void CEntityStateVec::DrawEntitiesRaw()
{

	
	for( std::map< std::string, CEntityVec * >::iterator iter = m_pEntities.begin();
		 iter != m_pEntities.end(); iter++ )
		{
		
			CEntityVec * v = iter->second;
			
			 v->DrawEntities( NULL );
			
		}
	
	
}

void CEntityStateVec::DrawEntitiesToFrameBuffers()
{
	
	for( std::map< std::string, CEntityVec * >::iterator iter = m_pEntities.begin();
		 iter != m_pEntities.end(); iter++ )
		{
		
			CEntityVec * v = iter->second;
			
			 v->DrawEntities( m_pFrameScene );
			
		}
	
}